package com.credithc.customers.base.service.impl;

import com.credithc.baseserv.core.message.MessageFactory;
import com.credithc.baseserv.core.utils.UUIDUtils;
import com.credithc.customers.base.codes.CustomerCodes;
import com.credithc.customers.base.constants.CustomerConstants;
import com.credithc.customers.base.exception.CustomerException;
import com.credithc.customers.base.mapper.CustomerExtendMapper;
import com.credithc.customers.base.mapper.CustomerIdInfoMapper;
import com.credithc.customers.base.mapper.PreCustomerFlowMapper;
import com.credithc.customers.base.mapper.PreCustomerMapper;
import com.credithc.customers.base.po.CustomerExtendPo;
import com.credithc.customers.base.po.CustomerIdInfoPo;
import com.credithc.customers.base.po.PreCustomerFlowPo;
import com.credithc.customers.base.po.PreCustomerInfoPo;
import com.credithc.customers.base.ro.BaseRequest;
import com.credithc.customers.base.ro.PreCustomerRo;
import com.credithc.customers.base.service.IBasePreCustomerService;
import com.credithc.customers.base.service.ICommonService;
import com.credithc.customers.base.utils.ClassUtils;
import com.credithc.customers.base.utils.CustomerUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhukai
 * @date 2018/12/20 14:10
 */
@Service
@Slf4j
public class BasePreCustomerServiceImpl implements IBasePreCustomerService {

    private final ICommonService commonService;

    private final PreCustomerMapper preCustomerMapper;

    private final PreCustomerFlowMapper preCustomerFlowMapper;

    private final CustomerExtendMapper customerExtendMapper;

    private final MessageFactory messageFactory;

    private final CustomerIdInfoMapper idInfoMapper;

    //private Lock lock = new ReentrantLock();

    @Autowired
    public BasePreCustomerServiceImpl(ICommonService commonService, PreCustomerMapper preCustomerMapper, PreCustomerFlowMapper preCustomerFlowMapper, CustomerExtendMapper customerExtendMapper, MessageFactory messageFactory, CustomerIdInfoMapper idInfoMapper) {
        this.commonService = commonService;
        this.preCustomerMapper = preCustomerMapper;
        this.preCustomerFlowMapper = preCustomerFlowMapper;
        this.customerExtendMapper = customerExtendMapper;
        this.messageFactory = messageFactory;
        this.idInfoMapper = idInfoMapper;
    }

    @Override
    public Map<String, String> createPreCustomerNo(BaseRequest<PreCustomerRo> request) {
        log.info("【创建用户号】接口开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>入参:{}", request);
        Integer status = CustomerConstants.STATUS_SUCCESS;
        String errorMsg = null;
        try {
            checkBusinessParam(request, false);
            PreCustomerRo ro = request.getBody();
            Map<String, String> map = new HashMap<>(2);
            map.put("requestNo", ro.getRequestNo());
            PreCustomerInfoPo currentPreCustomer = commonService.getExistPreCustomer(ro.getContactType(), ro.getContactInfo());
            if (currentPreCustomer != null) {
                ((BasePreCustomerServiceImpl) AopContext.currentProxy()).insertPreCustomer(request, currentPreCustomer, false);
                //更新hhy hyr密码
//                if (StringUtils.isNotBlank(ro.getPassword())) {
//                    updatePreCustomer(currentPreCustomer, request.getSubSystemSign(), ro.getPassword());
//                }
                map.put("preCustomerNo", currentPreCustomer.getPreCustomerNo());
            } else {
                String preCustomerNo = ((BasePreCustomerServiceImpl) AopContext.currentProxy()).insertPreCustomer(request, false);
                map.put("preCustomerNo", preCustomerNo);
            }
            return map;
        } catch (CustomerException e) {
            log.info("【创建用户号】接口开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName());
            status = CustomerConstants.STATUS_FAIL;
            errorMsg = StringUtils.isNotBlank(e.getMsg()) ? e.getMsg() : messageFactory.getInstance(e.getCode()).getMsg();
            throw new CustomerException(e.getCode(), e.getMsg());
        } finally {
            insertPreCustomerFlow(request, status, errorMsg);
        }
    }

    @Override
    public Map<String, String> createPreCustomerNo4Import(BaseRequest<PreCustomerRo> request) {
        try {
            checkBusinessParam(request, true);
            Map<String, String> map = new HashMap<>(2);
            map.put("requestNo", request.getBody().getRequestNo());
            PreCustomerRo ro = request.getBody();
            PreCustomerInfoPo currentPreCustomer = commonService.getExistPreCustomer(ro.getContactType(), ro.getContactInfo());
            if (currentPreCustomer != null) {
                insertCustomerExtend(request.getSystemSign(), request.getSubSystemSign(), request.getBody().getRemark(), currentPreCustomer.getPreCustomerNo());
                map.put("preCustomerNo", currentPreCustomer.getPreCustomerNo());
            } else {
                String preCustomerNo = ((BasePreCustomerServiceImpl) AopContext.currentProxy()).insertPreCustomer(request, true);
                map.put("preCustomerNo", preCustomerNo);
            }
            return map;
        } catch (CustomerException e) {
            log.info("【创建用户号】接口异常>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName());
            throw new CustomerException(e.getCode(), e.getMsg());
        }
    }

    private void checkBusinessParam(BaseRequest<PreCustomerRo> request, boolean isImport) {
        PreCustomerRo ro=request.getBody();
        if (!isImport) {
            PreCustomerRo.checkBaseParam(ro);
            //优化效率，去掉流水号校验
//            commonService.checkRepeatRequestNo(preCustomerRo.getRequestNo(), TableEnum.PRE_CUSTOMER_FLOW);
            String customerName = ro.getCustomerName();
            String idCardType = ro.getIdCardType();
            String idCardNo = ro.getIdCardNo();
            if (StringUtils.isNotBlank(customerName) && StringUtils.isNotBlank(idCardType) && StringUtils.isNotBlank(idCardNo)) {
                throw new CustomerException(CustomerCodes.PARAM_VALIDATE_ERROR, "三要素齐全,请直接创建客户");
            } else {
                if (StringUtils.isNotBlank(idCardType)) {
                    CustomerUtils.checkIdCardType(idCardType);
                }
                if (StringUtils.isNotBlank(idCardType) && StringUtils.isNotBlank(idCardNo)) {
                    CustomerUtils.checkIdCardTypeAndNo(idCardType, idCardNo);
                }
            }
        }
        CustomerUtils.checkContact(ro.getContactType(), ro.getContactInfo());
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertPreCustomer(BaseRequest<PreCustomerRo> request, PreCustomerInfoPo currentPreCustomer, boolean isImport) {
        String associatePreNo = request.getBody().getAssociatePreNo();
//        CustomerUtils.verifyAssociatedPreNo(associatePreNo);
        String systemSign = request.getSystemSign();
        String subSystemSign = request.getSubSystemSign();
        String remark = request.getBody().getRemark();
        if (StringUtils.isNotBlank(associatePreNo)) {
            String[] arr = verifyAssociatedPreNoWithDb(associatePreNo, systemSign, subSystemSign);
            for (String no : arr) {
                insertCustomerExtend(systemSign, subSystemSign, remark, currentPreCustomer.getPreCustomerNo(), no);
                commonService.updateRelation(systemSign, subSystemSign, no, currentPreCustomer.getPreCustomerNo());
                commonService.updateCustomerProduct(systemSign, subSystemSign, no, currentPreCustomer.getPreCustomerNo());
            }
        } else {
            insertCustomerExtend(systemSign, subSystemSign, remark, currentPreCustomer.getPreCustomerNo());
        }
        //todo 用户注册不再更新cust_id_info表，该数据当下并无意义
//        if (!isImport) {
//            updateOrInsertCustomerIdInfo(currentPreCustomer.getPreCustomerNo(), request);
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertPreCustomer(BaseRequest<PreCustomerRo> request, boolean isImport) {
        String systemSign = request.getSystemSign();
        String subSystemSign = request.getSubSystemSign();
        PreCustomerRo ro = request.getBody();
        String associatePreNo = ro.getAssociatePreNo();
        String[] arr = new String[0];
        if (StringUtils.isNotBlank(associatePreNo)) {
            CustomerUtils.verifyAssociatedPreNo(associatePreNo);
            arr = verifyAssociatedPreNoWithDb(associatePreNo, systemSign, subSystemSign);
        }
        PreCustomerInfoPo po = new PreCustomerInfoPo();
        BeanUtils.copyProperties(ro, po);
        // HHY和HYR密码处理
//        String password = ro.getPassword();
//        if (StringUtils.isBlank(password)) {
//            password = "";
//        }
//        if (subSystemSign.equals(CustomerConstants.HHR_JK)) {
//            po.setHhrJkPasswd(password);
//        } else if (subSystemSign.equals(CustomerConstants.HHR_CF)) {
//            po.setHhrCfPasswd(password);
//        } else if (subSystemSign.equals(CustomerConstants.HYR_CF)) {
//            po.setHyrCfPasswd(password);
//        } else if (subSystemSign.equals(CustomerConstants.HYR_JK)) {
//            po.setHyrJkPasswd(password);
//        }
        po.setId(UUIDUtils.getUUID());
        String preCustomerNo = CustomerUtils.generatePreCustomerNo();
        po.setPreCustomerNo(preCustomerNo);
        po.setContactVerified(CustomerConstants.STATUS_CONTACT_UNVERIFIED);
        try {
            po.setCreateTime(new Timestamp(System.currentTimeMillis()));
            po.setCreateDate(new Date(System.currentTimeMillis()));
            preCustomerMapper.insert(po);
        } catch (DataAccessException e) {
            log.error("插入cust_pre_info报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
            throw new CustomerException(CustomerCodes.DATABASE_ERROR_INSERT);
        }
        if (arr.length > 0) {
            for (String no : arr) {
                insertCustomerExtend(systemSign, subSystemSign, request.getBody().getRemark(), preCustomerNo, no);
                commonService.updateRelation(systemSign, subSystemSign, no, preCustomerNo);
                commonService.updateCustomerProduct(systemSign, subSystemSign, no, preCustomerNo);
            }
        } else {
            insertCustomerExtend(systemSign, subSystemSign, request.getBody().getRemark(), preCustomerNo);
        }
        //todo 用户注册不再更新cust_id_info表，该数据当下并无意义
//        if (!isImport) {
//            if (StringUtils.isNotBlank(ro.getIdCardType()) || StringUtils.isNotBlank(ro.getIdCardNo()) || StringUtils.isNotBlank(ro.getCustomerName())) {
//                CustomerIdInfoRo idRo = new CustomerIdInfoRo(ro.getIdCardType(), ro.getIdCardNo(), ro.getCustomerName(), false);
//                commonService.insertCustomerIdInfo(idRo, preCustomerNo, request, null, true);
//            }
//        }
        return preCustomerNo;
    }

    @Override
    public Map<String, String> createUnifyPreCustomerNo(BaseRequest<PreCustomerRo> request) {
        log.info("创建统一用户号接口开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>入参:{}", request);
        try {
            checkBusinessParam(request, false);
            PreCustomerRo ro = request.getBody();
            Map<String, String> map = new HashMap<>(2);
            map.put("requestNo", ro.getRequestNo());
            PreCustomerInfoPo currentPreCustomer = commonService.getExistPreCustomer(ro.getContactType(), ro.getContactInfo());
            if (currentPreCustomer != null) {
                ((BasePreCustomerServiceImpl) AopContext.currentProxy()).insertPreCustomer(request, currentPreCustomer, false);
                map.put("preCustomerNo", currentPreCustomer.getPreCustomerNo());
            } else {
                String preCustomerNo = ((BasePreCustomerServiceImpl) AopContext.currentProxy()).insertPreCustomer(request, false);
                map.put("preCustomerNo", preCustomerNo);
            }
            //新增统一用户密码,新用户依据一账通规则生成密码
            if (StringUtils.isNotBlank(ro.getPassword())) {
                commonService.insertPreCustomerPass(map.get("preCustomerNo"), request.getSystemSign(), request.getSubSystemSign(), ro.getPassword(), ro.getContactInfo());
            }
            insertPreCustomerFlow(request, CustomerConstants.STATUS_SUCCESS, null);
            return map;
        } catch (CustomerException e) {
            log.info("创建统一用户号接口异常>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName());
            insertPreCustomerFlow(request, CustomerConstants.STATUS_FAIL, StringUtils.isNotBlank(e.getMsg()) ? e.getMsg() : messageFactory.getInstance(e.getCode()).getMsg());
            throw new CustomerException(e.getCode(), e.getMsg());
        }
    }

    @Override
    public void insertPreCustomerFlow(BaseRequest<PreCustomerRo> request, int status, String errorMessage) {
        try {
            PreCustomerRo ro = request.getBody();
            PreCustomerFlowPo po = new PreCustomerFlowPo();
            po.setId(UUIDUtils.getUUID());
            po.setRequestNo(ro.getRequestNo());
            po.setContactType(ro.getContactType());
            po.setContactInfo(ro.getContactInfo());
            po.setContactVerified(((ro.getContactVerified() != null && ro.getContactVerified()) ? CustomerConstants.STATUS_CONTACT_VERIFIED : CustomerConstants.STATUS_CONTACT_UNVERIFIED));
            po.setAssociatePreNo(ro.getAssociatePreNo());
            po.setSystemSign(request.getSystemSign());
            po.setSubSystemSign(request.getSubSystemSign());
            po.setCustomerName(ro.getCustomerName());
            po.setIdCardType(ro.getIdCardType());
            po.setIdCardNo(ro.getIdCardNo());
            po.setStatus(status);
//            po.setPassword(ro.getPassword());
            if (status == CustomerConstants.STATUS_SUCCESS) {
                po.setRemark(ro.getRemark());
            } else {
                po.setRemark(errorMessage);
            }
            po.setCreateTime(new Timestamp(System.currentTimeMillis()));
            preCustomerFlowMapper.insert(po);
        } catch (DataAccessException e) {
            log.info("插入用户流水报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
            throw new CustomerException(CustomerCodes.DATABASE_ERROR_INSERT);
        }
    }

    @Override
    public void insertCustomerExtend(String systemSign, String subSystemSign, String remark, String preCustomerNo) {
        try {
            CustomerExtendPo currentPo = new CustomerExtendPo();
            currentPo.setPreCustomerNo(preCustomerNo);
            currentPo.setSystemSign(systemSign);
            currentPo.setSubSystemSign(subSystemSign);
            currentPo.setStatus(1);
            int res = customerExtendMapper.selectCount(currentPo);
            if (res == 0) {
                currentPo.setId(UUIDUtils.getUUID());
                currentPo.setRemark(remark);
                currentPo.setCreateTime(new Timestamp(System.currentTimeMillis()));
                customerExtendMapper.insert(currentPo);
            }
        } catch (DataAccessException e) {
            log.error("插入用户扩展信息表cust_extend报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
            throw new CustomerException(CustomerCodes.DATABASE_ERROR_INSERT);
        }
    }

    @Override
    public void insertCustomerExtend(String systemSign, String subSystemSign, String remark, String preCustomerNo, String associatedPreNo) {
        try {
            CustomerExtendPo extendPo = new CustomerExtendPo();
            extendPo.setPreCustomerNo(preCustomerNo);
            extendPo.setSystemSign(systemSign);
            extendPo.setSubSystemSign(subSystemSign);
            extendPo.setAssociatePreNo(associatedPreNo);
            int res = customerExtendMapper.selectCount(extendPo);
            if (res == 0) {
                extendPo.setId(UUIDUtils.getUUID());
                extendPo.setRemark(remark);
                extendPo.setCreateTime(new Timestamp(System.currentTimeMillis()));
                customerExtendMapper.insert(extendPo);
            }
        } catch (DataAccessException e) {
            log.info("插入用户扩展信息报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
            throw new CustomerException(CustomerCodes.DATABASE_ERROR_INSERT);
        }
    }

    private void updateOrInsertCustomerIdInfo(String customerNo, BaseRequest<PreCustomerRo> request) {
        try {
            String customerName = request.getBody().getCustomerName();
            String idCardType = request.getBody().getIdCardType();
            String idCardNo = request.getBody().getIdCardNo();
            if (StringUtils.isNotBlank(customerName) || StringUtils.isNotBlank(idCardType) || StringUtils.isNotBlank(idCardNo)) {
                CustomerIdInfoPo idInfoPo = new CustomerIdInfoPo();
                idInfoPo.setCustomerNo(customerNo);
                idInfoPo.setCustomerName(customerName);
                idInfoPo.setIdCardType(idCardType);
                idInfoPo.setIdCardNo(idCardNo);
                List<CustomerIdInfoPo> ids = idInfoMapper.select(idInfoPo);
                if (ids.size() > 0) {
                    //todo 子系统标识修改
                    idInfoPo = ids.get(0);
                    String systems = idInfoPo.getSubSystemSign();
                    if (StringUtils.isNotBlank(systems)) {
                        if (!systems.contains(request.getSubSystemSign())) {
                            idInfoPo.setSubSystemSign(systems + "," + request.getSubSystemSign());
                            idInfoPo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                            idInfoMapper.updateByPrimaryKey(idInfoPo);
                        }
                    }
                } else {
                    idInfoPo.setId(UUIDUtils.getUUID());
                    idInfoPo.setSubSystemSign(request.getSubSystemSign());
                    idInfoPo.setCustomerProperty(CustomerConstants.CUSTOMER_PROPERTY_PRE);
                    idInfoPo.setElementsVerified(CustomerConstants.STATUS_ELEMENTS_UNVERIFIED);
                    idInfoPo.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    idInfoMapper.insert(idInfoPo);
                }
            }
        } catch (DataAccessException e) {
            log.info("创建用户的时候在更新客户id信息表是报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
            throw new CustomerException(CustomerCodes.DATABASE_ERROR);
        }
    }

    private String[] verifyAssociatedPreNoWithDb(String associatedPreNo, String systemSign, String subSystemSign) {
        //判断当前系统下是否有该关联用户号
        if (StringUtils.isNotBlank(associatedPreNo)) {
            String[] arr = associatedPreNo.split(",");
            for (String no : arr) {
                List<CustomerExtendPo> list = commonService.getExistPreCustomerExtendList(no, systemSign, subSystemSign);
                if (list == null || list.size() == 0) {
                    throw new CustomerException(CustomerCodes.BIZ_VALIDATE_ERROR, no + "对应的相关联的用户号不存在");
                } else {
                    for (CustomerExtendPo extendPo : list) {
                        if (StringUtils.isNotBlank(extendPo.getCustomerNo())) {
                            throw new CustomerException(CustomerCodes.PRE_CUSTOMERNO_CONVERTED, "关联用户号" + no + "已经转化为客户号,客户号:'" + extendPo.getCustomerNo() + "'");
                        }
                        List<CustomerExtendPo> existAssociatedPreCustomerExtendList = commonService.getExistAssociatedPreCustomerExtendList(no, systemSign, subSystemSign);
                        if (existAssociatedPreCustomerExtendList.size() > 0) {
                            String message = "该客户号已被其他用户号关联,客户号为'" + existAssociatedPreCustomerExtendList.get(0).getPreCustomerNo();
                            throw new CustomerException(CustomerCodes.PRE_CUSTOMERNO_CONVERTED, message);
                        }

                    }
                }
            }
            return arr;
        }
        return new String[0];
    }

//    public void updatePreCustomer(PreCustomerInfoPo po, String subSystemSign, String password) {
//        try {
//            // HHY和HYR密码处理
//            if (subSystemSign.equals(CustomerConstants.HHR_JK)) {
//                po.setHhrJkPasswd(password);
//            } else if (subSystemSign.equals(CustomerConstants.HHR_CF)) {
//                po.setHhrCfPasswd(password);
//            } else if (subSystemSign.equals(CustomerConstants.HYR_CF)) {
//                po.setHyrCfPasswd(password);
//            } else if (subSystemSign.equals(CustomerConstants.HYR_JK)) {
//                po.setHyrJkPasswd(password);
//            }
//            po.setUpdateTime(new Timestamp(System.currentTimeMillis()));
//            preCustomerMapper.updateByPrimaryKeySelective(po);
//        } catch (DataAccessException e) {
//            log.info("创建用户更新cust_pre_info相关信息报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
//            throw new CustomerException(CustomerCodes.DATABASE_ERROR_UPDATE);
//        }
//    }

    @Override
    public Map<String, String> createPreCustomerNoOnly(BaseRequest<PreCustomerRo> request) {
        log.info("创建用户号接口开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>入参:{}", request);
        Integer status = CustomerConstants.STATUS_SUCCESS;
        String errorMsg = null;
        try {
//            checkBusinessParam(request, false);
            PreCustomerRo ro = request.getBody();
            PreCustomerInfoPo po = new PreCustomerInfoPo();
            BeanUtils.copyProperties(ro, po);
            po.setId(UUIDUtils.getUUID());
            String preCustomerNo = CustomerUtils.generatePreCustomerNo();
            po.setPreCustomerNo(preCustomerNo);
            po.setContactVerified(CustomerConstants.STATUS_CONTACT_VERIFIED);
            try {
                po.setCreateTime(new Timestamp(System.currentTimeMillis()));
                po.setCreateDate(new Date(System.currentTimeMillis()));
                preCustomerMapper.insert(po);
            } catch (DataAccessException e) {
                log.info("插入用户报错:" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName() + "--" + e.getMessage());
                throw new CustomerException(CustomerCodes.DATABASE_ERROR_INSERT);
            }
            Map<String, String> map = new HashMap<>(2);
            map.put("requestNo", ro.getRequestNo());
            map.put("preCustomerNo", preCustomerNo);
            return map;
        } catch (CustomerException e) {
            log.info("创建用户失败" + ClassUtils.getClassName() + "--" + ClassUtils.getMethodName());
            status = CustomerConstants.STATUS_FAIL;
            errorMsg = StringUtils.isNotBlank(e.getMsg()) ? e.getMsg() : messageFactory.getInstance(e.getCode()).getMsg();
            throw new CustomerException(e.getCode(), e.getMsg());
        } finally {
            insertPreCustomerFlow(request, status, errorMsg);
        }
    }
}